/*
 *      Copyright (c) 2018-2028, Chill Zhuang All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the dreamlu.net developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: Chill 庄骞 (smallchill@163.com)
 */
package org.springblade.modules.admin.service.impl;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.modules.admin.dto.ContractAgreeDTO;
import org.springblade.modules.admin.entity.*;
import org.springblade.modules.admin.enums.ElevatorMaintainStatusEnums;
import org.springblade.modules.admin.service.IBuildingContractPlusService;
import org.springblade.modules.admin.vo.ContractAgreeVO;
import org.springblade.modules.admin.mapper.ContractAgreeMapper;
import org.springblade.modules.admin.service.IContractAgreeService;
import org.springblade.core.mp.base.BaseServiceImpl;
import org.springblade.modules.admin.vo.contract.ContractAgreeStatusVo;
import org.springblade.modules.admin.vo.contract.ElevatorAgreeVo;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 合同协议 服务实现类
 *
 * @author ysq
 * @since 2025-03-27
 */
@Service
public class ContractAgreeServiceImpl extends BaseServiceImpl<ContractAgreeMapper, ContractAgree> implements IContractAgreeService {

	/**
	 * "协议状态1:待回签2:待审核3:待生效4:待完结(已生效)5:合同待回签6:合同已回签7:审核不通过8:已终止9:已作废10:已关闭",11取消作废，12：取消关闭
	 */
	private final Integer[] AGREE_STATUS = {-1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};


	/**
	 * "状态1:未审核，2:审核通过，3审核未通过
	 */
	private final Integer[] CHECK_STATUS = {-1, 1, 2, 3};


	@Autowired
	private IBuildingContractPlusService buildingContractPlusService;

	@Autowired
	private IUserService userService;

	@Autowired
	@Lazy
	private IContractAgreeService contractAgreeService;

	@Override
	public void add(ContractAgree contractAgree) {
		if (contractAgree.getCheckUserId() != null) {
			User service = userService.getById(contractAgree.getCheckUserId());
			if (service != null) {
				contractAgree.setCheckUserName(Convert.toStr(service.getRealName()));
			}
		}
		if (Convert.toInt(contractAgree.getIsDrafts(), -1) == 0) {
			//非草稿箱先走校验逻辑
			check(contractAgree);
		}
		if (contractAgree.getId() != null) {
			update(contractAgree);
			return;
		}
		//非草稿箱
		List<ContractAgreeStatusVo> contractAgreeStatusVos = agreeStatusListInit();
		if (!Convert.toBool(contractAgree.getIsDrafts(), false)) {
			if (contractAgree.getParentId() != null) {
				ContractAgree agree = this.getById(contractAgree.getParentId());
				agree.setAgreeStatus(AGREE_STATUS[8]);
				agree.setAgreeStatusDate(new Date());
				agree.setStopUpdateDate(new Date());
				agree.setStopDate(new Date());
				agree.setOtherDesc("再增协议-自动终止");
				this.updateById(agree);
			}
			//属于新增
			if (Convert.toInt(contractAgree.getBackSignType(), 0) == 0) {
				contractAgree.setAgreeStatus(AGREE_STATUS[1]);
				contractAgree.setStatus(CHECK_STATUS[0]);
				agreeStatusUpdate(contractAgreeStatusVos, AGREE_STATUS[1]);
			} else {
				contractAgree.setAgreeStatus(AGREE_STATUS[2]);
				contractAgree.setStatus(CHECK_STATUS[1]);
				agreeStatusUpdate(contractAgreeStatusVos, AGREE_STATUS[1]);
				agreeStatusUpdate(contractAgreeStatusVos, AGREE_STATUS[2]);
			}
		}
		contractAgree.setAgreeStatusList(contractAgreeStatusVos);
		contractAgree.setCreateUserName(AuthUtil.getNickName());
		this.saveOrUpdate(contractAgree);
	}

	@Override
	public void update(ContractAgree contractAgree) {
		//先走校验逻辑
		if (Convert.toInt(contractAgree.getIsDrafts(), -1) == 0) {
			//非草稿箱先走校验逻辑
			check(contractAgree);
		}
		//非草稿箱
		ContractAgree agree = this.getById(contractAgree.getId());
		if (Convert.toInt(contractAgree.getIsDrafts(), 0) == 0) {
			if (Convert.toInt(contractAgree.getBackSignType(), 0) == 0) {
				contractAgree.setAgreeStatus(AGREE_STATUS[1]);
			} else {
				contractAgree.setAgreeStatus(AGREE_STATUS[2]);
				contractAgree.setStatus(CHECK_STATUS[1]);
				List<ContractAgreeStatusVo> statusVoList = JSON.parseArray(JSON.toJSONString(agree.getAgreeStatusList()), ContractAgreeStatusVo.class);
				agreeStatusUpdate(statusVoList, AGREE_STATUS[2]);
				contractAgree.setAgreeStatusList(statusVoList);
			}
		}
		this.updateById(contractAgree);
	}

	@Override
	public IPage<ContractAgreeVO> pageList(ContractAgreeDTO contractAgreeDTO) {
		if (contractAgreeDTO.getIsDrafts() == null) {
			contractAgreeDTO.setIsDrafts(false);
		}
		Query query = new Query();
		query.setSize(contractAgreeDTO.getSize());
		query.setCurrent(contractAgreeDTO.getCurrent());
		IPage<ContractAgreeVO> page = Condition.getPage(query);
		List<ContractAgreeVO> agreeList = baseMapper.pageList(page, contractAgreeDTO);
		page.setRecords(agreeList);
		return page;
	}

	@Override
	public void updateStatus(ContractAgree contractAgree) {
		if (contractAgree.getId() == null) {
			contractAgree.setId(-1L);
		}
		if (contractAgree.getStatus() == null) {
			contractAgree.setStatus(-1);
		}
		if (contractAgree.getAgreeStatus() == null) {
			contractAgree.setAgreeStatus(-1);
		}
		ContractAgree agree = this.getById(contractAgree.getId());
		if (agree != null) {
			if (agree.getCheckUserId() != null) {
				User service = userService.getById(agree.getCheckUserId());
				if (service != null) {
					agree.setCheckUserName(Convert.toStr(service.getRealName()));
				}
			}

			//审核不通过
			if (contractAgree.getStatus().equals(CHECK_STATUS[3])) {
				if (agree.getStatus().equals(CHECK_STATUS[2]) || agree.getStatus().equals(CHECK_STATUS[3])) {
					throw new ServiceException("已变更状态请刷新页面");
				}
				agree.setAgreeStatus(AGREE_STATUS[7]);
				agree.setStatus(CHECK_STATUS[3]);
				agree.setStatusDesc(contractAgree.getStatusDesc());
			}
			//审核通过
			if (contractAgree.getStatus().equals(CHECK_STATUS[2])) {
				if (agree.getStatus().equals(CHECK_STATUS[2]) || agree.getStatus().equals(CHECK_STATUS[3])) {
					throw new ServiceException("已变更状态请刷新页面");
				}
				agree.setStatus(CHECK_STATUS[2]);
				List<ContractAgreeStatusVo> agreeStatusList = JSON.parseArray(JSON.toJSONString(agree.getAgreeStatusList()), ContractAgreeStatusVo.class);
				if (agree.getBeginTime().getTime() < System.currentTimeMillis() && agree.getEndTime().getTime() > System.currentTimeMillis()) {
					agree.setAgreeStatus(AGREE_STATUS[4]);
					agreeStatusUpdate(agreeStatusList, AGREE_STATUS[3]);
					agreeStatusUpdate(agreeStatusList, AGREE_STATUS[4]);
				} else {
					agreeStatusUpdate(agreeStatusList, AGREE_STATUS[3]);
					agree.setAgreeStatus(AGREE_STATUS[3]);
				}
				agree.setAgreeStatusList(agreeStatusList);
				agree.setStatusDesc(contractAgree.getStatusDesc());
			}

			//已关闭
			if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[10])) {
				agree.setAgreeStatusDate(new Date());
				agree.setAgreeStatus(AGREE_STATUS[10]);
				agree.setOtherDesc(contractAgree.getStatusDesc());
			}

			//作废
			if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[9])) {
				agree.setAgreeStatusDate(new Date());
				agree.setAgreeStatus(AGREE_STATUS[9]);
				agree.setOtherDesc(contractAgree.getStatusDesc());
			}

			//终止-不做处理
			if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[8])) {
				agree.setStopDate(contractAgree.getStopDate());
				agree.setOtherDesc(contractAgree.getStatusDesc());
				agree.setStopUpdateDate(new Date());
			}

			//取消作废--
			if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[11])) {
				check(contractAgree);
				//如果合同的结束时间被占用
				if (agree.getBeginTime().getTime() < System.currentTimeMillis() && agree.getEndTime().getTime() > System.currentTimeMillis()) {
					agree.setAgreeStatus(AGREE_STATUS[4]);
				} else {
					agree.setAgreeStatus(AGREE_STATUS[3]);
				}

			}
			//取消关闭
			if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[12])) {
				check(contractAgree);
				if (agree.getStatus().equals(CHECK_STATUS[3])) {
					agree.setAgreeStatus(AGREE_STATUS[7]);
				} else {
					agree.setAgreeStatus(AGREE_STATUS[1]);
				}
			}
		}
		//已回签
		if (contractAgree.getAgreeStatus().equals(AGREE_STATUS[6])) {
			if (agree == null) {
				List<ContractAgree> list = this.list(Wrappers.<ContractAgree>lambdaQuery().eq(ContractAgree::getContractId, contractAgree.getContractId()));
				for (ContractAgree contractAgree1 : list) {
					//通过合同页面添加
					List<ContractAgreeStatusVo> agreeStatusList = JSON.parseArray(JSON.toJSONString(contractAgree1.getAgreeStatusList()), ContractAgreeStatusVo.class);
					agreeStatusUpdate(agreeStatusList, (AGREE_STATUS[6]));
					contractAgree1.setAgreeStatus(AGREE_STATUS[6]);
					contractAgree1.setAgreeStatusList(agreeStatusList);
					this.updateById(contractAgree1);
				}
				return;
			} else {
				//通过协议添加
				List<ContractAgreeStatusVo> agreeStatusList = JSON.parseArray(JSON.toJSONString(agree.getAgreeStatusList()), ContractAgreeStatusVo.class);
				agreeStatusUpdate(agreeStatusList, (AGREE_STATUS[6]));
				agree.setAgreeStatus(AGREE_STATUS[6]);
				agree.setAgreeStatusList(agreeStatusList);
				this.updateById(agree);
				return;
			}

		}
		this.updateById(agree);
	}

	@Override
	public List<ElevatorContract> notPlanEleHasContract(DateTime yesterday) {
		if (yesterday != null) {
			List<ElevatorContract> elevatorContracts = baseMapper.notPlanEleHasContract(Convert.toInt(DateUtil.format(yesterday, "yyyyMMdd")));
			List<ElevatorContract> contractList = contractAgreeService.getNotPlan(yesterday, null);
			List<ElevatorContract> contractList1 = contractList.stream().filter(o -> !elevatorContracts.stream().map(ElevatorContract::getElevatorId).collect(Collectors.toList()).contains(o.getElevatorId())).collect(Collectors.toList());
			elevatorContracts.addAll(contractList1);
			return elevatorContracts;
		} else {
			List<ElevatorContract> elevatorContracts = baseMapper.notPlanEleHasContract(null);
			List<ElevatorContract> contractList = contractAgreeService.getNotPlan(null, null);
			List<ElevatorContract> contractList1 = contractList.stream().filter(o -> !elevatorContracts.stream().map(ElevatorContract::getElevatorId).collect(Collectors.toList()).contains(o.getElevatorId())).collect(Collectors.toList());
			elevatorContracts.addAll(contractList1);
			return elevatorContracts;
		}
	}

	@Override
	public List<ElevatorAgreeVo> getElevatorAgreeList(Long elevatorId) {
		List<ElevatorAgreeVo> elevatorConList1 = baseMapper.getElevatorConList(elevatorId);
		List<ElevatorAgreeVo> elevatorConList2 = baseMapper.getElevatorAgreeList(elevatorId);
		elevatorConList1.addAll(elevatorConList2);
		Collections.sort(elevatorConList1);
		return elevatorConList1;
	}

	@Override
	public List<ContractAgreeVO> downExcel(ContractAgreeDTO contractAgreeDTO) {
		return baseMapper.pageList(null, contractAgreeDTO);
	}

	@Override
	public List<ElevatorContract> getNotPlan(Date date, Long elevatorId) {
		return baseMapper.getNotPlan(date, elevatorId);
	}


	/**
	 * 新增校验逻辑
	 * 1.合同（新建） 提交的时候判断
	 * 1.1所有的梯，只要有电梯，拟定在保，不允许创建
	 * 1.2所有的梯，都脱保，合同开始时间，大于所有电梯的结束时间/终止时间
	 * 1.3剩下的情况，合同开始时间都要和所有电梯命中合同的时间首尾相连，有一个梯连不上都提示
	 * <p>
	 * 2.赠送合同/协议列表
	 * 2.1所有梯命中的合同，合同管理状态需要即将到期或者待续签，才显示在弹窗里面，才允许创建关联的赠送合同/协议
	 * 2.2通过上面的合同创建赠送合同/不停保协议，创建的时候再使用合同的规则在判定一次
	 *
	 * @param contractAgree
	 */
	private void check(ContractAgree contractAgree) {
		//第一步校验协议编号是否相同
		ContractAgree agree = this.getOne(Wrappers.<ContractAgree>lambdaQuery().eq(ContractAgree::getAgreeNo, contractAgree.getAgreeNo()).eq(ContractAgree::getIsDrafts, 0));
		if (agree != null && !Convert.toLong(contractAgree.getId(), -1L).equals(agree.getId())) {
			throw new ServiceException("协议编号相同不能重复");
		}


		Long contractId = contractAgree.getContractId();
		List<ContractAgree> contractAgreeList = this.list(Wrappers.<ContractAgree>lambdaQuery().eq(ContractAgree::getContractId, contractId).eq(ContractAgree::getIsDrafts, 0).orderByDesc(ContractAgree::getCreateTime));
		contractAgreeList = contractAgreeList.stream().filter(o -> !o.getId().equals(Convert.toLong(contractAgree.getId(), -1L))).collect(Collectors.toList());


		//校验合同绑定的协议状态---只有待回签或者已终止才允许创建
		List<ContractAgree> agreeList = contractAgreeList.stream().filter(o -> o.getAgreeStatus().equals(AGREE_STATUS[5]) || o.getAgreeStatus().equals(AGREE_STATUS[8])).collect(Collectors.toList());
		if (agreeList.size() == 0 && contractAgreeList.size() > 0) {
			throw new ServiceException("该合同已经绑定其它协议,只有待回签或者已终止才允许创建,不满足协议编号:" + contractAgreeList.get(0).getAgreeNo());
		}

		//校验新增
		List<MaintainPlanConfig> elevatorContract = baseMapper.getElevatorContract(contractAgree.getContractId());
		List<Integer> maintainStatus = elevatorContract.stream().map(MaintainPlanConfig::getMaintainStatus).collect(Collectors.toList());
		//为空表示是新梯
		if (maintainStatus.size() == 0) {
			return;
		}
		//第一步 判断拟定在保--如果包含不允许创建
		List<MaintainPlanConfig> list = elevatorContract.stream().filter(o -> o.getMaintainStatus() == ElevatorMaintainStatusEnums.DIS_ENABLE.getId()).collect(Collectors.toList());
		if (list.size() > 0) {
			throw new ServiceException("电梯维保状态存在拟定在保不允许创建,项目名称:" + list.get(0).getBuildingName() + ",电梯名称:" + list.get(0).getElevatorAddress());
		}
		//第二步判断 是否全部所有的梯，都脱保--都脱保允许创建
		List<MaintainPlanConfig> list2 = elevatorContract.stream().filter(o -> o.getMaintainStatus() == ElevatorMaintainStatusEnums.RELEASE_INSURANCE.getId()).collect(Collectors.toList());
		if (list2.size() == maintainStatus.size()) {
			return;
		}
		//包含脱保，又包含在保内或者在保外---不允许创建
		if (list2.size() > 0 && list2.size() < maintainStatus.size()) {
			throw new ServiceException("该合同绑定的电梯存在脱保的情况,不允许创建项目名称:" + list2.get(0).getBuildingName() + ",电梯名称:" + list2.get(0).getElevatorAddress());
		}

		for (ContractAgree one : contractAgreeList) {
			//如果合同的开始时间被占用
			if (one.getStopDate() != null && one.getStopDate().getTime() < one.getEndTime().getTime()) {
				one.setEndTime(one.getStopDate());
			}
			if (contractAgree.getBeginTime().getTime() >= one.getBeginTime().getTime() && contractAgree.getBeginTime().getTime() <= one.getEndTime().getTime()) {
				throw new ServiceException("已经被其它协议占用不允许创建..占用协议编号=" + one.getAgreeNo());
			}
			//如果合同的结束时间被占用
			if (contractAgree.getEndTime().getTime() >= one.getBeginTime().getTime() && contractAgree.getEndTime().getTime() <= one.getEndTime().getTime()) {
				throw new ServiceException("已经被其它协议占用不允许创建..占用协议编号=" + one.getAgreeNo());
			}
		}

		//校验新增：第三步 只有 在保（合同期内）或者 在保（合同期外）----上下两份协议，时间必须连贯
		if (contractAgreeList.size() > 0) {
			ContractAgree contractAgree1 = contractAgreeList.get(0);
			if (contractAgree1.getStopDate() != null && contractAgree1.getStopDate().getTime() < contractAgree1.getEndTime().getTime()) {
				contractAgree1.setEndTime(contractAgree1.getStopDate());
			}
			if (contractAgree.getBeginTime().getTime() < contractAgree1.getEndTime().getTime()) {
				throw new ServiceException("当前协议必须大于上一份协议时间结束时间上一份协议编号=" + contractAgree1.getAgreeNo());
			}
			long between = DateUtil.betweenDay(contractAgree1.getEndTime(), contractAgree.getBeginTime(), true);
			if (between > 1) {
				throw new ServiceException("当前协议必须和上一份协议时间连贯,上一份协议编号=" + contractAgree1.getAgreeNo());
			}
			return;
		}

		//校验新增：第三步 只有 在保（合同期内）或者 在保（合同期外）----上下两份协议，时间必须连贯
		BuildingContractPlus buildingContractPlus = buildingContractPlusService.getById(contractAgree.getContractId());
		if (buildingContractPlus.getStopTime() != null && buildingContractPlus.getStopTime().getTime() < buildingContractPlus.getContractEndTime().getTime()) {
			buildingContractPlus.setContractEndTime(buildingContractPlus.getStopTime());
		}

		if (contractAgree.getBeginTime().getTime() < buildingContractPlus.getContractEndTime().getTime()) {
			throw new ServiceException("当前协议开始时间必须大于【" + buildingContractPlus.getContractNo() + "】的结束时间");
		}
		long between2 = DateUtil.betweenDay(buildingContractPlus.getContractEndTime(), contractAgree.getBeginTime(), true);
		if (between2 > 1) {
			throw new ServiceException("协议必须和选中的合同首尾连贯");
		}


	}

	/**
	 * 协议进度初始化
	 *
	 * @return
	 */
	private List<ContractAgreeStatusVo> agreeStatusListInit() {

		List<ContractAgreeStatusVo> agreeStatusList = new ArrayList<>(16);
		ContractAgreeStatusVo contractAgreeStatusVo1 = new ContractAgreeStatusVo();
		contractAgreeStatusVo1.setStatusDesc("待回签(已创建)");
		contractAgreeStatusVo1.setStatus(AGREE_STATUS[1]);
		agreeStatusList.add(contractAgreeStatusVo1);


		ContractAgreeStatusVo contractAgreeStatusVo2 = new ContractAgreeStatusVo();
		contractAgreeStatusVo2.setStatusDesc("待审核(已提审)");
		contractAgreeStatusVo2.setStatus(AGREE_STATUS[2]);
		agreeStatusList.add(contractAgreeStatusVo2);


		ContractAgreeStatusVo contractAgreeStatusVo3 = new ContractAgreeStatusVo();
		contractAgreeStatusVo3.setStatusDesc("待生效(已通过)");
		contractAgreeStatusVo3.setStatus(AGREE_STATUS[3]);
		agreeStatusList.add(contractAgreeStatusVo3);

		ContractAgreeStatusVo contractAgreeStatusVo4 = new ContractAgreeStatusVo();
		contractAgreeStatusVo4.setStatusDesc("待完结(已生效)");
		contractAgreeStatusVo4.setStatus(AGREE_STATUS[4]);
		agreeStatusList.add(contractAgreeStatusVo4);

		ContractAgreeStatusVo contractAgreeStatusVo5 = new ContractAgreeStatusVo();
		contractAgreeStatusVo5.setStatusDesc("合同待回签(已完结)");
		contractAgreeStatusVo5.setStatus(AGREE_STATUS[5]);
		agreeStatusList.add(contractAgreeStatusVo5);

		ContractAgreeStatusVo contractAgreeStatusVo6 = new ContractAgreeStatusVo();
		contractAgreeStatusVo6.setStatusDesc("合同已回签");
		contractAgreeStatusVo6.setStatus(AGREE_STATUS[6]);
		agreeStatusList.add(contractAgreeStatusVo6);

		return agreeStatusList;
	}

	/**
	 * 协议进度更新时间
	 */
	private void agreeStatusUpdate(List<ContractAgreeStatusVo> list, Integer status) {
		for (ContractAgreeStatusVo contractAgreeStatusVo : list) {
			if (contractAgreeStatusVo.getStatus().equals(status)) {
				contractAgreeStatusVo.setUpdateDate(DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
				contractAgreeStatusVo.setCreateUserName(AuthUtil.getNickName());
			}
		}
	}


}
